﻿/*!
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

using System;
using System.Configuration;
using System.Threading.Tasks;

namespace Pittypat
{
    /// <summary>
    /// 默认的授权服务，当配置文件中没有配置 authorityService 时使用该默认服务。不能从外部创建该类的对象实例。该服务不执行任何操作，也不会产生异常。
    /// </summary>
    sealed class AuthorityService : IAuthorityService
    {
        #region Current

        /// <summary>
        /// 默认的服务实例，这是一个只读静态字段。
        /// </summary>
        static readonly AuthorityService Default = new AuthorityService();

        // 当前配置的服务或默认服务。
        static IAuthorityService service = null;
        // 用于同步对 service 的访问。
        static readonly object serviceLock = new object();

        /// <summary>
        /// 获取当前配置文件中定义的授权服务，如果配置文件中没有定义，则返回一个默认的服务对象。
        /// </summary>
        internal static IAuthorityService Current
        {
            get
            {
                if (service == null)
                {
                    lock (serviceLock)
                    {
                        if (service == null)
                        {
                            // 配置文件中定义的服务类型名称。
                            var typeName = Configuration.PittypatConfig.Current.AuthorityService;

                            if (!string.IsNullOrEmpty(typeName))
                            {
                                // 加载服务类型
                                var type = Type.GetType(typeName);
                                if (type != null)
                                {
                                    // 创建服务对象实例
                                    service = Activator.CreateInstance(type) as IAuthorityService;
                                }
                                else
                                {
                                    // 找不到类型时产生一个配置错误
                                    throw new ConfigurationErrorsException(string.Format("没有找到类型为 {0} 的授权服务。", typeName));
                                }
                            }
                            else
                            {
                                // 配置文件没有定义有效的名称，使用默认服务
                                service = Default;
                            }
                        }
                    }
                }

                return service;
            }
        }

        #endregion

        /// <summary>
        /// 初始化 AuthorityService 类的新实例。
        /// </summary>
        AuthorityService()
        {
        }

        /// <summary>
        /// 异步获取当前系统在目标授权服务中的系统令牌。总是返回空字符串令牌。
        /// </summary>
        /// <param name="systemId">系统的 Id。当前系统在目标服务中注册的 Id。</param>
        /// <param name="systemKey">系统的密钥。当前系统获取访问目标服务令牌时需要提供的密钥。</param>
        /// <param name="progress">跟踪和汇报异步操作的进度。</param>
        /// <returns>系统令牌。</returns>
        Task<string> IAuthorityService.GetSystemTokenAsync(string systemId, string systemKey, IAsyncProgress progress)
        {
            return Task.FromResult("");
        }

        /// <summary>
        /// 异步使用指定的用户名和密码登录当前系统。总是返回匿名用户。
        /// </summary>
        /// <param name="systemToken">此前已经通过 GetSystemToken 获取到的系统令牌。</param>
        /// <param name="loginName">用户登录名称。</param>
        /// <param name="password">用户登录密码的明文。</param>
        /// <param name="progress">跟踪和汇报异步操作的进度。</param>
        /// <returns>登录结果，使用 LoginResult.IsAnonymous 判断是否匿名用户。</returns>
        Task<LoginResult> IAuthorityService.LoginAsync(string systemToken, string loginName, string password, IAsyncProgress progress)
        {
            return Task.FromResult(LoginResult.Anonymous);
        }

        /// <summary>
        /// 异步注销指定令牌的用户。不执行任何操作。
        /// </summary>
        /// <param name="systemToken">此前已经通过 GetSystemToken 获取到的系统令牌。</param>
        /// <param name="userToken">要注销的用户的用户令牌。</param>
        /// <param name="progress">跟踪和汇报异步操作的进度。</param>
        /// <returns>异步任务。</returns>
        Task IAuthorityService.LogoutAsync(string systemToken, string userToken, IAsyncProgress progress)
        {
            return Task.FromResult("");
        }

        /// <summary>
        /// 异步验证指定的用户是否对指定路径的功能具有权限。总是返回未授权的匿名用户权限。
        /// </summary>
        /// <param name="systemToken">此前已经通过 GetSystemToken 获取到的系统令牌。</param>
        /// <param name="userToken">用户令牌。</param>
        /// <param name="funcPath">目标功能的完整路径。当传递空引用或空字符串时，用于返回指定令牌的用户的用户信息。</param>
        /// <param name="progress">跟踪和汇报异步操作的进度。</param>
        /// <returns>返回作为验证结果的用户和授权信息，如果返回空引用，则使用未授权的匿名用户。</returns>
        Task<Permission> IAuthorityService.DemandAsync(string systemToken, string userToken, string funcPath, IAsyncProgress progress)
        {
            return Task.FromResult(Permission.AnonymousUnauthorized);
        }

        /// <summary>
        /// 异步加载指定用户拥有权限的所有 App 和模块的列表，也就是导航列表。总是返回空导航列表。
        /// </summary>
        /// <param name="systemToken">此前已经通过 GetSystemToken 获取到的系统令牌。</param>
        /// <param name="userToken">用户令牌。</param>
        /// <param name="progress">跟踪和汇报异步操作的进度。</param>
        /// <returns>返回指定用户拥有权限的 App 和模块的列表。</returns>
        Task<NavList> IAuthorityService.NavListAsync(string systemToken, string userToken, IAsyncProgress progress)
        {
            return Task.FromResult(NavList.Empty);
        }
    }
}
